﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Serviio.API
{
    public class ServiioPresentation
    {
        private const string endpoint = "/rest/presentation";
        private ServiioConnection conn = null;
        
        public string Language { get; set; }
        public bool ShowParentCategoryTitle { get; set; }
        public List<ServiioBrowsingCategory> Categories { get; private set; }

        private List<ServiioBrowsingCategory> flatCategories;
        public List<ServiioBrowsingCategory> FlatCategories
        {
            get
            {
                if (flatCategories == null)
                {
                    flatCategories = new List<ServiioBrowsingCategory>();
                    FlattenCategoryList(flatCategories, Categories);
                }
                return flatCategories;
            }
        }

        private void FlattenCategoryList(List<ServiioBrowsingCategory> flatList, List<ServiioBrowsingCategory> list)
        {
            foreach (ServiioBrowsingCategory category in list)
            {
                flatList.Add(category);
                if (category.SubCategories.Count > 0)
                    FlattenCategoryList(flatList, category.SubCategories);
            }
        }

        internal ServiioPresentation(ServiioConnection connection)
        {
            this.conn = connection;
            Categories = new List<ServiioBrowsingCategory>();
            Refresh();
        }

        public bool Refresh()
        {
            try
            {
                XmlDocument xDoc = RESTHelper.Get(conn.Host + endpoint);

                Language = xDoc.SelectSingleNode("/presentation/language").InnerText;
                ShowParentCategoryTitle = Boolean.Parse(xDoc.SelectSingleNode("/presentation/showParentCategoryTitle").InnerText);

                Categories.Clear();
                flatCategories = null;

                XmlNodeList categoryNodes = xDoc.SelectNodes("/presentation/categories/browsingCategory");
                RefreshCategories(Categories, categoryNodes);
            }
            catch
            {
                return false;
            }

            return true;
        }

        private void RefreshCategories(List<ServiioBrowsingCategory> list, XmlNodeList nodes)
        {
            foreach (XmlNode node in nodes)
            {
                string id = node.SelectSingleNode("id").InnerText;
                string title = node.SelectSingleNode("title").InnerText;
                string visibility = node.SelectSingleNode("visibility").InnerText;
                ServiioBrowsingCategory category = new ServiioBrowsingCategory(id, title, visibility);

                XmlNodeList subCategoryNodes = node.SelectNodes("subCategories/browsingCategory");
                if (subCategoryNodes != null && subCategoryNodes.Count > 0)
                    RefreshCategories(category.SubCategories, subCategoryNodes);

                list.Add(category);
            }
        }

        public bool Update()
        {
            try
            {
                XmlDocument xDoc = new XmlDocument();
                XmlDeclaration xDec = xDoc.CreateXmlDeclaration("1.0", null, null);
                xDoc.AppendChild(xDec);
                XmlElement xRoot = xDoc.CreateElement("presentation");
                xDoc.AppendChild(xRoot);

                XmlElement xCategories = xDoc.CreateElement("categories");
                UpdateCategories(xDoc, xCategories, Categories);
                xRoot.AppendChild(xCategories);

                XmlElement xLanguage = xDoc.CreateElement("language");
                xLanguage.InnerText = Language;
                xRoot.AppendChild(xLanguage);

                XmlElement xShowParentCategoryTitle = xDoc.CreateElement("showParentCategoryTitle");
                xShowParentCategoryTitle.InnerText = ShowParentCategoryTitle.ToString();
                xRoot.AppendChild(xShowParentCategoryTitle);

                return RESTHelper.Put(conn.Host + endpoint, xDoc);
            }
            catch
            {
                return false;
            }
        }

        private void UpdateCategories(XmlDocument xDoc, XmlElement xCategories, List<ServiioBrowsingCategory> list)
        {
            foreach (ServiioBrowsingCategory category in list)
            {
                XmlElement xCategory = xDoc.CreateElement("browsingCategory");
                xCategories.AppendChild(xCategory);

                XmlElement xId = xDoc.CreateElement("id");
                xId.InnerText = category.Id;
                xCategory.AppendChild(xId);

                XmlElement xVisibility = xDoc.CreateElement("visibility");
                xVisibility.InnerText = category.VisibilityString;
                xCategory.AppendChild(xVisibility);

                if (category.SubCategories.Count > 0)
                {
                    XmlElement xSubCategories = xDoc.CreateElement("subCategories");
                    UpdateCategories(xDoc, xSubCategories, category.SubCategories);
                    xCategory.AppendChild(xSubCategories);
                }
            }
        }
    }
}
